#!/bin/bash

# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Script that emerges packages and their dependencies from a host development
# machine onto a target Chromium OS device
#
# NOTE: This script must be run from the chromiumos build chroot environment.
#

# Load common constants.  This should be the first executable line.
# The path to common.sh should be relative to your script's location.
. /usr/lib/crosutils/common.sh 2> /dev/null ||
  (echo "Must run from within the chroot" && false) ||
  exit 1

# Flags
DEFINE_string board "$DEFAULT_BOARD" \
  "The board to build packages for."
DEFINE_boolean usepkg $FLAGS_FALSE \
  "Use binary packages to bootstrap build when possible."
DEFINE_integer jobs -1 \
  "How many packages to build in parallel at maximum."
DEFINE_boolean unmerge $FLAGS_FALSE \
  "Whether to unmerge the package versus emerge it."
DEFINE_boolean onstatefuldev $FLAGS_TRUE \
  "Build packages and install them into stateful partition on device."
DEFINE_boolean installmask $FLAGS_TRUE \
  "Use INSTALL_MASK to shrink the resulting image."
DEFINE_string remote "" "remote hostname/IP of running Chromium OS instance"

# Parse command line
FLAGS_HELP="usage: $0 [flags]"
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"

# Die on any errors.
set -e

# Checks $1 and prints out $2 is required before exiting if $1 does not exist
check_args() {
  if [ -z "${1}" ] ; then
    echo "Error: ${2} is required."
    exit 1
  fi
}

# Clean up function for mount point
cleanup_sshfs_mount() {
  echo "Cleaning up mount point"
  sudo umount "${REMOTE_ROOT_DIR}"
}

check_args "${FLAGS_board}"
check_args "${FLAGS_ARGV}" "Emerge package name"

EMERGE_FLAGS=""
[[ $FLAGS_usepkg -eq $FLAGS_TRUE ]] &&
  EMERGE_FLAGS="${EMERGE_FLAGS} --getbinpkg --usepkg --with-bdeps y"

INSTALL_MASK=""
[[ ${FLAGS_installmask} -eq ${FLAGS_TRUE} ]] && \
  INSTALL_MASK="${DEFAULT_INSTALL_MASK}"

EMERGE_JOBS=
[[ ${FLAGS_jobs} -ne -1 ]] && EMERGE_JOBS="--jobs=${FLAGS_jobs}"

# Duplicate from build_packages to get host packages on system.

# Skip building on host if we are unmerging.
if [ ${FLAGS_unmerge} -eq ${FLAGS_FALSE} ] ; then
  sudo emerge -uDNv $EMERGE_FLAGS $EMERGE_JOBS world

  # Build request and install them onto the sysroot
  for emerge_request in $FLAGS_ARGV; do
    sudo emerge-${FLAGS_board} $EMERGE_JOBS -uDNv \
      $(remove_quotes "${emerge_request}")
  done
fi

# Name is unique per client.  This allows one to run gmergefs in parallel
# with multiple clients.
REMOTE_ROOT_DIR="/build/${FLAGS_board}/gmergefs/${FLAGS_remote}"

# Default is to install on stateful dev, otherwise install on root.
REMOTE_RELATIVE_PATH=""
[ ${FLAGS_onstatefuldev} -eq $FLAGS_TRUE ] && \
  REMOTE_RELATIVE_PATH="mnt/stateful_partition/dev_image"
REMOTE_PATH="${REMOTE_ROOT_DIR}/${REMOTE_RELATIVE_PATH}"

# Create directory for remote image
sudo mkdir -p "${REMOTE_ROOT_DIR}"

# Mount remote fs into chroot
echo "Enter password for remote machine"
sudo sshfs -o idmap=user -o allow_other -o nonempty -o transform_symlinks \
  "root@${FLAGS_remote}:/" "${REMOTE_ROOT_DIR}"

trap cleanup_sshfs_mount EXIT

# Ensure root path is created for emerge
sudo mkdir -p "${REMOTE_PATH}"

# Same arguments used in build_image to emerge these packages onto the target
for emerge_request in $FLAGS_ARGV; do
  if [ ${FLAGS_unmerge} -eq ${FLAGS_FALSE} ] ; then
    sudo INSTALL_MASK="$INSTALL_MASK" emerge-${FLAGS_board} \
      --root="${REMOTE_PATH}" --root-deps=rdeps \
      --usepkgonly $(remove_quotes "${emerge_request}") $EMERGE_JOBS
  else
    sudo emerge-${FLAGS_board} --unmerge \
      --root="${REMOTE_PATH}" $(remove_quotes "${emerge_request}")
  fi
done

# Update ld.so.cache of root partition if installing to /usr/local
if [ ${FLAGS_onstatefuldev} -eq $FLAGS_TRUE ] ; then
  # Re-run ldconfig to fix /etc/ldconfig.so.cache
  sudo /sbin/ldconfig -r "${REMOTE_ROOT_DIR}"
fi

sync
sudo umount "${REMOTE_ROOT_DIR}"

trap - EXIT
